package com.nightpiter.controller.algorithms;

/**
 * Way class for Dijkstra's Algorithm
 * 
 * Package protected
 * 
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
@SuppressWarnings("unchecked")
class Way implements Comparable {

	/**
	 * tunnel sum distance to the startVertex
	 */
	protected int tunnelDistance;

	/**
	 * tunnel hops needed to reach the startVertex
	 */
	protected int tunnelHops;

	/**
	 * sum transfer distance to the startVertex
	 */
	protected int transferDistance;

	/**
	 * transfer hops needed to reach the startVertex
	 */
	protected int transferHops;

	/**
	 * edge to pass through
	 */
	private Edge edge;

	/**
	 * default constructor
	 */
	public Way() {
		set(0, 0, 0, 0);
	}

	/**
	 * creates an instance with custom info
	 */
	public Way(int tunnelDistance, int tunnelHops, int transferDistance,
			int transferHops) {
		set(tunnelDistance, tunnelHops, transferDistance, transferHops);
	}

	/**
	 * creates an instance with info copied from another instance
	 */
	public Way(Way other) {
		set(other.tunnelDistance, other.tunnelHops, other.transferDistance,
				other.transferHops);
	}

	/**
	 * creates an instance with info copied from another instance
	 */
	public Way(Way other, Edge edge) {
		set(other.tunnelDistance, other.tunnelHops, other.transferDistance,
				other.transferHops);
		add(edge);
		this.edge = edge;
	}

	/**
	 * adds custom values to the current info
	 */
	public void add(int tunnelDistance, int tunnelHops, int transferDistance,
			int transferHops) {
		this.tunnelDistance += tunnelDistance;
		this.tunnelHops += tunnelHops;
		this.transferDistance += transferDistance;
		this.transferHops += transferHops;
	}

	/**
	 * adds another instance info values to the current info
	 */
	public void add(Way other) {
		this.tunnelDistance += other.tunnelDistance;
		this.tunnelHops += other.tunnelHops;
		this.transferDistance += other.transferDistance;
		this.transferHops += other.transferHops;
	}

	/**
	 * resets fields to provided values
	 */
	protected void set(int tunnelDistance, int tunnelHops,
			int transferDistance, int transferHops) {
		this.tunnelDistance = tunnelDistance;
		this.tunnelHops = tunnelHops;
		this.transferDistance = transferDistance;
		this.transferHops = transferHops;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	public int compareTo(Object other) {
		if (other instanceof Way) {
			return this.transferHops - ((Way) other).transferHops;
		} else {
			return this.transferHops - (Integer) other;
		}
	}

	/**
	 * compares with another way by total distance
	 * 
	 * @param other
	 *            the way to compare with
	 * @return the difference between ways' distances
	 */
	public int compareByDistance(Way other) {
		return this.transferDistance - other.transferDistance
				+ this.tunnelDistance - other.tunnelDistance;
	}

	/**
	 * compares with another way by transfer hops
	 * 
	 * @param other
	 *            the way to compare with
	 * @return the difference between ways' transfer hops counts
	 */
	public int compareByHops(Way other) {
		return this.transferHops - other.transferHops;
	}

	/**
	 * @return the edge
	 */
	Edge getEdge() {
		return edge;
	}

}
